﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Utilities.Data;
using System.Data;

namespace Utilities
{
    public class FileHelp
    {

        #region 文件架构
        private static DataTable _fileListSchema;
        private static DataTable _folderHistorySchema;


        /// <summary>
        /// 文件列表的架构(目录下的文件列表)
        /// </summary>
        public static DataTable FileListSchema
        {
            get
            {
                if (_fileListSchema == null)
                {

                    _fileListSchema = new DataTable();
                    _fileListSchema.Columns.Add("FileName", typeof(string));    //文件名
                    _fileListSchema.Columns.Add("FileSize", typeof(int));       //大小
                    _fileListSchema.Columns.Add("CreateTime", typeof(string));  //创建时间
                }
                return _fileListSchema.Clone();
            }
        }

        /// <summary>
        /// 文件夹更新历史
        /// </summary>
        public static DataTable FolderHistorySchema
        {
            get
            {
                if (_folderHistorySchema == null)
                {
                    _folderHistorySchema = new DataTable();
                    _folderHistorySchema.Columns.Add("Folder", typeof(string));      //文件夹
                    _folderHistorySchema.Columns.Add("OperatTime", typeof(DateTime)); //操作时间
                }
                return _folderHistorySchema.Clone();
            }
        }


        #endregion

        #region 文件转换为字节
        /// <summary>
        /// 文件转换为字节
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="writeTime">文件写入的时间</param>
        /// <returns></returns>
        public static byte[] FileConvertToByte(string filePath, out DateTime createTime, out DateTime lastWriteTime)
        {
            FileInfo fileInfo = new FileInfo(filePath);

            createTime = fileInfo.CreationTime;
            lastWriteTime = fileInfo.LastWriteTime;

            using (FileStream fileStream = fileInfo.OpenRead())
            {
                Byte[] fileData = new Byte[fileStream.Length];
                fileStream.Read(fileData, 0, fileData.Length);
                return fileData;
            }
        }


        /// <summary>
        /// 文件转换为字节
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        public static byte[] FileConvertToByte(string filePath)
        {
            DateTime createTime, lastWriteTime;
            return FileConvertToByte(filePath, out createTime, out lastWriteTime);
        }
        #endregion

        #region 字节转换文件
        /// <summary>
        /// 字节转换文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="fileData">文件数据</param>
        public static void ByteConvertToFile(string filePath, byte[] fileData, DateTime? createTime, DateTime? lastWriteTime)
        {
            if (fileData == null || fileData.Length == 0)
                return;
            FileInfo fileInfo = new FileInfo(filePath);
            if (!fileInfo.Directory.Exists)
                fileInfo.Directory.Create();

            using (FileStream fileStream = fileInfo.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                fileStream.Write(fileData, 0, fileData.Length);
            }

            if (createTime != null)
                fileInfo.CreationTime = createTime.Value;
            if (lastWriteTime != null)
                fileInfo.LastWriteTime = lastWriteTime.Value;

        }

        /// <summary>
        /// 字节转换文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="fileData">文件数据</param>
        public static void ByteConvertToFile(string filePath, byte[] fileData)
        {
            ByteConvertToFile(filePath, fileData, null, null);
        }
        #endregion

        #region 根据目录创建文件列表(相当于目录索引)
        /// <summary>
        /// 根据目录创建文件列表
        /// </summary>
        /// <param name="dirInfo">目录信息</param>
        /// <param name="isIncludSubdirectories">是否包括子目录</param>
        public static void CreateFileList(DirectoryInfo dirInfo, bool isIncludSubdirectories)
        {


            //可能要文件锁 arrayList存放日期来做 锁同步
            string filePath = dirInfo.FullName + "\\" + dirInfo.Name + ".xml";

            if (File.Exists(filePath))
                File.Delete(filePath);

            DataTable data = FileListSchema;
            data.TableName = Guid.NewGuid().ToString().Replace("-", "");

            //文件信息列表 把文件信息写入

            foreach (FileInfo fileInfo in dirInfo.GetFiles())
            {
                data.Rows.Add(new object[] { fileInfo.Name, fileInfo.Length, fileInfo.CreationTime });
            }
            data.WriteXml(filePath, XmlWriteMode.WriteSchema);

            //递归子目录
            if (isIncludSubdirectories)
            {
                foreach (DirectoryInfo itemInfo in dirInfo.GetDirectories())
                {
                    CreateFileList(itemInfo, isIncludSubdirectories);
                }
            }
        }

        /// <summary>
        /// 根据目录创建文件列表
        /// </summary>
        /// <param name="dirInfo">目录信息</param>
        public static void CreateFileList(DirectoryInfo dirInfo)
        {
            CreateFileList(dirInfo, false);
        }

        #endregion

        #region 文件的压缩、解压
        /// <summary>
        /// 把指定路径文件生成字节
        /// </summary>
        /// <param name="filePath">文件完整路径</param>
        /// <returns>字节</returns>
        public static byte[] FileCompressToByte(string filePath)
        {
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
            {
                return DataCompression.Compress(fileStream);
            }
        }


        /// <summary>
        /// 把字节生成文件
        /// </summary>
        /// <param name="filePath">文件完整路径</param>
        /// <param name="compressData">压缩的数据</param>
        public static void ByteDecompressToFile(string filePath, byte[] compressData)
        {
            MemoryStream ms = new MemoryStream(compressData);
            byte[] fileData = DataCompression.Decompress(ms);
            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                fs.Write(fileData, 0, fileData.Length);
            }
        }
        #endregion

        #region   CopyFiles
        /// <summary>
        /// 拷贝文件夹
        /// </summary>
        /// <param name="fromDirectory"></param>
        /// <param name="toDirectory"></param>
        public static void CopyDirectory(string fromDirectory, string toDirectory)
        {

            if (!Directory.Exists(fromDirectory))
                return;

            Directory.CreateDirectory(toDirectory);



            string[] directories = Directory.GetDirectories(fromDirectory);

            if (directories.Length > 0)
            {
                foreach (string d in directories)
                {
                    CopyDirectory(d, toDirectory + d.Substring(d.LastIndexOf("\\")));
                }
            }

            string[] files = Directory.GetFiles(fromDirectory);

            if (files.Length > 0)
            {
                foreach (string s in files)
                {
                    string toName = toDirectory + s.Substring(s.LastIndexOf("\\"));

                    if (File.Exists(toName))
                    {
                        RemveFilesReadonly(new FileInfo(toName));
                    }

                    File.Copy(s, toName, true);



                }
            }
        }
        #endregion

        #region ClearDir
        /// <summary>
        /// 清除目录 子文件和目录
        /// </summary>
        /// <param name="dirList"></param>
        public static void ClearDirList(params  string[] dirList)
        {
            foreach (string dir in dirList)
            {
                ClearDirList(new DirectoryInfo(dir));
            }

        }

        /// <summary>
        /// 清除目录 子文件和目录
        /// </summary>
        /// <param name="dirInfo"></param>
        private static void ClearDirList(params DirectoryInfo[] dirInfoList)
        {
            foreach (DirectoryInfo dirInfo in dirInfoList)
            {
                if (!dirInfo.Exists)
                    continue;

                RemveFilesReadonly(dirInfo.GetFiles("*.*", SearchOption.AllDirectories));

                foreach (var childFile in dirInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly))
                {

                    childFile.Delete();
                }

                foreach (var childDir in dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly))
                {
                    childDir.Delete(true);
                }
            }
        }


        #endregion

        #region 移除文件的只读属性
        /// <summary>
        /// 移除文件的只读属性
        /// </summary>
        /// <param name="files"></param>
        public static void RemveFilesReadonly(params FileInfo[] files)
        {
            foreach (var fileInfo in files)
            {
                if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0)
                    fileInfo.Attributes &= ~FileAttributes.ReadOnly;
            }
        }
        #endregion

        #region DeleteDir
        /// <summary>
        /// 删除目录 子目录和所有文件
        /// </summary>
        /// <param name="dir"></param>
        public static void DeleteDir(string dir)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(dir);

            DeleteDir(dirInfo);
        }


        /// <summary>
        /// 删除目录 子目录和所有文件
        /// </summary>
        /// <param name="dirInfo"></param>
        public static void DeleteDir(DirectoryInfo dirInfo)
        {
            if (!dirInfo.Exists)
                return;

            RemveFilesReadonly(dirInfo.GetFiles("*.*", SearchOption.AllDirectories));
            dirInfo.Delete();
        }
        #endregion


        #region 读写文件流
        /// <summary>
        /// 将一个流中的数据读取到另外一个流中
        /// </summary>
        /// <param name="readStream"></param>
        /// <param name="writeStream"></param>
        public static void ReadWriteStream(Stream readStream, Stream writeStream)
        {
            int Length = 256;
            Byte[] buffer = new Byte[Length];
            int bytesRead = readStream.Read(buffer, 0, Length);
            while (bytesRead > 0)
            {
                writeStream.Write(buffer, 0, bytesRead);
                bytesRead = readStream.Read(buffer, 0, Length);
            }
            readStream.Close();
            writeStream.Close();

        }
        #endregion

    }
}
